﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Project.Database.Repository
{
    public partial class DatabaseRepository
    {
        #region Properties

        public int NumberOfUsers
        {
            get
            {
                return this.entities.Users.Count();
            }
        }

        #endregion

        #region Query Methods

        public IQueryable<User> GetAllUsers()
        {
            return from user in entities.Users
                   orderby user.UserName
                   select user;
        }

        public User GetUser(int id)
        {
            return entities.Users.SingleOrDefault(user => user.ID == id);
        }

        public User GetUser(string userName)
        {
            return entities.Users.SingleOrDefault(user => user.UserName == userName);
        }

        public Profile GetProfile(string userName)
        {
            return GetUser(userName).Profile;
        }

        public IQueryable<User> GetUsersForRole(string roleName)
        {
            return GetUsersForRole(GetRole(roleName));
        }

        public IQueryable<User> GetUsersForRole(int id)
        {
            return GetUsersForRole(GetRole(id));
        }

        public IQueryable<User> GetUsersForRole(Role role)
        {
            if (!RoleExists(role))
                throw new ArgumentException(MissingRole);

            return from user in entities.Users
                   where user.RoleID == role.ID
                   orderby user.UserName
                   select user;
        }
        #endregion

        #region Insert/Delete

        private void AddUser(User user)
        {
            if (UserExists(user))
                throw new ArgumentException(TooManyUser);

            entities.Users.AddObject(user);
        }

        public void CreateUser(string firstname, string lastname, string username, string password, int roleID, string email, string userIP)
        {
            Role role = GetRole(roleID);

            if (string.IsNullOrEmpty(username.Trim()))
                throw new ArgumentException("The user name provided is invalid. Please check the value and try again.");
            if (string.IsNullOrEmpty(password.Trim()))
                throw new ArgumentException("The password provided is invalid. Please enter a valid password value.");
            if (!RoleExists(role))
                throw new ArgumentException("The role selected for this user does not exist! Contact an administrator!");
            if (this.entities.Users.Any(user => user.UserName == username))
                throw new ArgumentException("Username already exists. Please enter a different user name.");

            DateTime now = DateTime.Now;
            User newUser = new User()
            {
                UserName = username,
                Password = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(password.Trim(), "md5"),
                Email = email,
                RoleID = role.ID,
                IP = userIP,
                DateCreated = now
            };

            if (role.ID == 7)
            {
                newUser.Profile = new Profile();
                newUser.Profile.FirstName = firstname;
                newUser.Profile.LastName = lastname;
                newUser.Profile.LastModified = now;
            }

            if (role.ID == 6)
            {
                newUser.Advertiser = new Advertiser();
                newUser.Advertiser.FirstName = firstname;
                newUser.Advertiser.LastName = lastname;
                newUser.Advertiser.LastModified = now;
                newUser.Advertiser.Budget = new Budget();
                newUser.Advertiser.Budget.Balance = 0;
                newUser.Advertiser.Budget.LastModified = now;
            }
       
            try
            {
                AddUser(newUser);
                // Immediately persist the user data
                Save();
            }
            catch (ArgumentException ae)
            {
                throw ae;
            }
            catch (Exception)
            {
                throw new ArgumentException("The authentication provider returned an error. Please verify your entry and try again. " +
                    "If the problem persists, please contact your system administrator.");
            }

        }

        public void DeleteUser(User user)
        {
            if (!UserExists(user))
                throw new ArgumentException(MissingUser);

            entities.Users.DeleteObject(user);
        }

        public void DeleteUser(string userName)
        {
            DeleteUser(GetUser(userName));
        }

        public void Logout(string username)
        {
            try
            {
                Login login = new Login();
                login.Action = false;
                login.Timestamp = DateTime.Now;
                GetUser(username).Logins.Add(login); //DONT RE-GET THE USER
                Save();
            }
            catch (Exception) { }
        }

        #endregion

        #region Helper Methods

        public bool UserExists(User user)
        {
            if (user == null)
                return false;

            return (entities.Users.SingleOrDefault(u => u.ID == user.ID || u.UserName == user.UserName) != null);
        }

        #endregion
    }
}